@iwonz/ywtc 0.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +4 -0
- package/CHANGELOG.md +56 -0
- package/LICENSE +21 -0
- package/README.md +267 -1
- package/dist/adapters/confluence.d.ts +46 -0
- package/dist/adapters/confluence.js +187 -0
- package/dist/adapters/confluence.js.map +1 -0
- package/dist/adapters/factory.d.ts +3 -0
- package/dist/adapters/factory.js +11 -0
- package/dist/adapters/factory.js.map +1 -0
- package/dist/adapters/yandex.d.ts +45 -0
- package/dist/adapters/yandex.js +233 -0
- package/dist/adapters/yandex.js.map +1 -0
- package/dist/cli-arguments.d.ts +41 -0
- package/dist/cli-arguments.js +149 -0
- package/dist/cli-arguments.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +180 -0
- package/dist/cli.js.map +1 -0
- package/dist/clients/confluence-cloud.d.ts +45 -0
- package/dist/clients/confluence-cloud.js +261 -0
- package/dist/clients/confluence-cloud.js.map +1 -0
- package/dist/clients/confluence-factory.d.ts +3 -0
- package/dist/clients/confluence-factory.js +8 -0
- package/dist/clients/confluence-factory.js.map +1 -0
- package/dist/clients/confluence.d.ts +42 -0
- package/dist/clients/confluence.js +286 -0
- package/dist/clients/confluence.js.map +1 -0
- package/dist/clients/yandex-wiki.d.ts +35 -0
- package/dist/clients/yandex-wiki.js +255 -0
- package/dist/clients/yandex-wiki.js.map +1 -0
- package/dist/config.d.ts +52 -0
- package/dist/config.js +177 -0
- package/dist/config.js.map +1 -0
- package/dist/content-model.d.ts +12 -0
- package/dist/content-model.js +416 -0
- package/dist/content-model.js.map +1 -0
- package/dist/conversion.d.ts +43 -0
- package/dist/conversion.js +450 -0
- package/dist/conversion.js.map +1 -0
- package/dist/doctor.d.ts +24 -0
- package/dist/doctor.js +45 -0
- package/dist/doctor.js.map +1 -0
- package/dist/domain.d.ts +202 -0
- package/dist/domain.js +18 -0
- package/dist/domain.js.map +1 -0
- package/dist/filesystem-export.d.ts +53 -0
- package/dist/filesystem-export.js +243 -0
- package/dist/filesystem-export.js.map +1 -0
- package/dist/graph.d.ts +13 -0
- package/dist/graph.js +121 -0
- package/dist/graph.js.map +1 -0
- package/dist/http.d.ts +26 -0
- package/dist/http.js +100 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/input.d.ts +4 -0
- package/dist/input.js +56 -0
- package/dist/input.js.map +1 -0
- package/dist/locators.d.ts +24 -0
- package/dist/locators.js +84 -0
- package/dist/locators.js.map +1 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.js +28 -0
- package/dist/logger.js.map +1 -0
- package/dist/migrator.d.ts +53 -0
- package/dist/migrator.js +669 -0
- package/dist/migrator.js.map +1 -0
- package/dist/rate-limiter.d.ts +12 -0
- package/dist/rate-limiter.js +31 -0
- package/dist/rate-limiter.js.map +1 -0
- package/dist/report.d.ts +101 -0
- package/dist/report.js +106 -0
- package/dist/report.js.map +1 -0
- package/dist/state.d.ts +119 -0
- package/dist/state.js +201 -0
- package/dist/state.js.map +1 -0
- package/dist/types.d.ts +197 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/updater.d.ts +24 -0
- package/dist/updater.js +92 -0
- package/dist/updater.js.map +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +8 -0
- package/dist/version.js.map +1 -0
- package/dist/workspace.d.ts +29 -0
- package/dist/workspace.js +157 -0
- package/dist/workspace.js.map +1 -0
- package/docs/assets/readme-header.png +0 -0
- package/package.json +108 -3
- package/ywtc.config.example.yaml +52 -0
package/.env.example
ADDED
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable changes to `ywtc` are documented in this file. Versions follow [Semantic Versioning](https://semver.org/).
|
|
4
|
+
|
|
5
|
+
## [2.0.1](https://github.com/iwonz/ywtc/compare/v2.0.0...v2.0.1) (2026-10-15)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **homebrew:** audit formula through temporary tap ([36062c4](https://github.com/iwonz/ywtc/commit/36062c4d802d2ed8294d877e5b88c05bf3f6fe73))
|
|
11
|
+
* **homebrew:** generate canonical npm formula ([76230ae](https://github.com/iwonz/ywtc/commit/76230ae879fda3d8d336d812dbc96adf50a1c11e))
|
|
12
|
+
* **homebrew:** honor dependency release cooldown ([cab4bc0](https://github.com/iwonz/ywtc/commit/cab4bc0a66b1ba9582c416c44830d8d133725c52))
|
|
13
|
+
* **homebrew:** infer version from registry URL ([327bdd1](https://github.com/iwonz/ywtc/commit/327bdd1dd2147a95c8703ab8a4bd36475955dc95))
|
|
14
|
+
* **release:** recover npm and Homebrew publication ([f91cb4e](https://github.com/iwonz/ywtc/commit/f91cb4e2c14359a0b47b1b601808a92c6f2ec6e5))
|
|
15
|
+
* **release:** run Homebrew after manual recovery ([b7bc73b](https://github.com/iwonz/ywtc/commit/b7bc73b35382ba1ad1cd5d808af4168b83fd8217))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Maintenance
|
|
19
|
+
|
|
20
|
+
* **release:** retry publication checks ([67cdbde](https://github.com/iwonz/ywtc/commit/67cdbdeb8e4c6c64b45e8b3127f71e6526dcfa70))
|
|
21
|
+
|
|
22
|
+
## [2.0.0](https://github.com/iwonz/ywtc/compare/v1.0.0...v2.0.0) (2026-10-15)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### ⚠ BREAKING CHANGES
|
|
26
|
+
|
|
27
|
+
* use --destination, --scope, and state v2; require Node.js 24 and npm 11.5.1.
|
|
28
|
+
* migration now requires the migrate subcommand and explicit deployment settings.
|
|
29
|
+
|
|
30
|
+
### Features
|
|
31
|
+
|
|
32
|
+
* generalize content transfer and static export ([a707f26](https://github.com/iwonz/ywtc/commit/a707f2670831c6c20277780bf02c651f920fbd28))
|
|
33
|
+
* ship ywtc v2 workspace and distribution ([1c4c8bd](https://github.com/iwonz/ywtc/commit/1c4c8bd9dc43ca1e0e36d6690019dae34b7dcfc8))
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Documentation
|
|
37
|
+
|
|
38
|
+
* clarify migration quick start ([d09a306](https://github.com/iwonz/ywtc/commit/d09a306637367592842d0653d0a382e46a774fbe))
|
|
39
|
+
* document first npm release bootstrap ([0496ccb](https://github.com/iwonz/ywtc/commit/0496ccbc1ac82c97ca0f80a75ce082ee1ffbb7ad))
|
|
40
|
+
* simplify README cover framing ([708e0ac](https://github.com/iwonz/ywtc/commit/708e0ac7da6d063532962e61ba3e58c9b5993a5d))
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
### Continuous Integration
|
|
44
|
+
|
|
45
|
+
* refresh GitHub Actions runtimes ([a6c33be](https://github.com/iwonz/ywtc/commit/a6c33be725ca2f5803e0cf7bd5277588f52b4afb))
|
|
46
|
+
|
|
47
|
+
## [1.0.0] - 2026-10-14
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
|
|
51
|
+
- Resumable migration of Yandex Wiki page trees to Confluence Data Center.
|
|
52
|
+
- YFM conversion, internal-link rewriting, attachments, images, tables, dynamic-grid snapshots, and readable degradation fallbacks.
|
|
53
|
+
- Automatic per-migration state, single-page mode, dry-run, rate controls, terminal progress, and HTML/JSON reports.
|
|
54
|
+
- Public documentation, release hygiene, Biome, Knip, tests, and the mandatory OpenSpec workflow.
|
|
55
|
+
|
|
56
|
+
[1.0.0]: https://github.com/iwonz/ywtc/releases/tag/v1.0.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,269 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/assets/readme-header.png" alt="Yandex Wiki and Confluence content moving through the ywtc pipeline" width="100%">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
# ywtc
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
`ywtc` — CLI для контролируемого переноса страниц между Yandex Wiki и Confluence, а также экспорта в Markdown или автономный HTML. Утилита сохраняет структуру, ссылки и вложения, отмечает деградации, проверяет результат и продолжает прерванную операцию по state-файлу. Исходные данные и страницы назначения автоматически не удаляются.
|
|
8
|
+
|
|
9
|
+
Требуются Node.js `>=24` и npm `>=11.5.1`.
|
|
10
|
+
|
|
11
|
+
## Возможности
|
|
12
|
+
|
|
13
|
+
| Что переносится | Результат |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| Страницы и иерархия | Одна страница, структурное поддерево или граф связанных страниц |
|
|
16
|
+
| Заголовки, текст, списки, цитаты, код, таблицы | Нативная разметка назначения, насколько это допускает формат |
|
|
17
|
+
| Внутренние ссылки и якоря | Переписываются на перенесённые страницы; внешние остаются внешними |
|
|
18
|
+
| Изображения и вложения | Потоковая передача с проверкой имени, размера и SHA-256 |
|
|
19
|
+
| Yandex notes, cuts, tabs и Grid | Ближайший нативный эквивалент; Grid становится статической таблицей |
|
|
20
|
+
| Confluence macros и resource identifiers | Сохраняются напрямую для same-vendor transfer либо преобразуются |
|
|
21
|
+
| Неподдерживаемые vendor-конструкции | Читаемый fallback и raw snapshot: attachment или файл в `_source/` |
|
|
22
|
+
| История, комментарии, пользователи, права, watchers | Не переносятся |
|
|
23
|
+
|
|
24
|
+
## Минимальный сценарий
|
|
25
|
+
|
|
26
|
+
- [ ] Установите CLI: `npm install -g @iwonz/ywtc`.
|
|
27
|
+
- [ ] Создайте workspace: `ywtc init`.
|
|
28
|
+
- [ ] Заполните `~/.ywtc/ywtc.config.yaml` и секреты в `~/.ywtc/.env`.
|
|
29
|
+
- [ ] Проверьте доступ: `ywtc doctor --source <source> --destination <destination>`.
|
|
30
|
+
- [ ] Выполните dry-run: `ywtc migrate --source <source> --destination <destination> --dry-run`.
|
|
31
|
+
- [ ] Повторите команду без `--dry-run`.
|
|
32
|
+
|
|
33
|
+
## Установка
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# npm
|
|
37
|
+
npm install -g @iwonz/ywtc
|
|
38
|
+
|
|
39
|
+
# без глобальной установки
|
|
40
|
+
npx @iwonz/ywtc@latest --version
|
|
41
|
+
|
|
42
|
+
# Homebrew
|
|
43
|
+
brew tap iwonz/ywtc https://github.com/iwonz/ywtc.git
|
|
44
|
+
brew install ywtc
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Проверить или установить обновление:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
ywtc update
|
|
51
|
+
ywtc update --install # только global npm или Homebrew
|
|
52
|
+
ywtc update --install --via brew
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Профили и workspace
|
|
56
|
+
|
|
57
|
+
Workspace выбирается в порядке `--workdir` → текущий каталог с `.ywtc-workspace.json` → `~/.ywtc`. Команда `init` идемпотентна и не перезаписывает существующие файлы:
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
~/.ywtc/
|
|
61
|
+
├── .ywtc-workspace.json
|
|
62
|
+
├── .env # только секреты, mode 0600
|
|
63
|
+
├── ywtc.config.yaml # подключения без секретов
|
|
64
|
+
└── .states/ # state, cache и HTML-отчёты
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Минимальная конфигурация двух подключений:
|
|
68
|
+
|
|
69
|
+
```yaml
|
|
70
|
+
schemaVersion: 2
|
|
71
|
+
defaults:
|
|
72
|
+
timeoutMs: 30000
|
|
73
|
+
concurrency: 4
|
|
74
|
+
|
|
75
|
+
connections:
|
|
76
|
+
wiki-prod:
|
|
77
|
+
type: yandex-wiki
|
|
78
|
+
apiUrl: https://api.wiki.yandex.net/v1
|
|
79
|
+
webUrl: https://wiki.example.ru
|
|
80
|
+
authType: oauth
|
|
81
|
+
tokenEnv: YANDEX_WIKI_TOKEN
|
|
82
|
+
organization: {type: yandex360, id: organization-id}
|
|
83
|
+
|
|
84
|
+
confluence-prod:
|
|
85
|
+
type: confluence
|
|
86
|
+
deployment: data-center
|
|
87
|
+
baseUrl: https://confluence.example.ru/confluence
|
|
88
|
+
authType: pat
|
|
89
|
+
tokenEnv: CONFLUENCE_TOKEN
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```dotenv
|
|
93
|
+
YANDEX_WIKI_TOKEN=
|
|
94
|
+
CONFLUENCE_TOKEN=
|
|
95
|
+
# Для Confluence Cloud:
|
|
96
|
+
CONFLUENCE_EMAIL=
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Полный шаблон с сетевыми лимитами находится в [`ywtc.config.example.yaml`](ywtc.config.example.yaml). Значения process environment имеют приоритет над `.env`. Секреты проверяются только для профилей, участвующих в текущей операции.
|
|
100
|
+
|
|
101
|
+
## Как получить токены
|
|
102
|
+
|
|
103
|
+
### Yandex Wiki
|
|
104
|
+
|
|
105
|
+
- [ ] Создайте приложение в [Яндекс OAuth](https://oauth.yandex.ru/) для доступа к API.
|
|
106
|
+
- [ ] Выдайте приложению права Wiki на чтение; для destination также нужны права записи.
|
|
107
|
+
- [ ] Получите OAuth-токен пользователя, имеющего доступ к нужным страницам. Для федеративного пользователя Yandex Cloud можно использовать IAM-токен и `authType: iam`.
|
|
108
|
+
- [ ] Найдите ID организации в **Yandex Tracker → Администрирование → Организации**.
|
|
109
|
+
- [ ] Укажите `organization.type: yandex360` для Яндекс 360 либо `cloud` для Cloud Organization.
|
|
110
|
+
- [ ] Сохраните токен в env-переменной, указанной в `tokenEnv`.
|
|
111
|
+
|
|
112
|
+
### Confluence Data Center
|
|
113
|
+
|
|
114
|
+
- [ ] Откройте **Avatar → Settings → Personal access tokens → Create token**.
|
|
115
|
+
- [ ] Создайте PAT и сохраните его в env-переменной из `tokenEnv`.
|
|
116
|
+
- [ ] Используйте `deployment: data-center` и `authType: pat`.
|
|
117
|
+
- [ ] Убедитесь, что пользователь может читать source и создавать/изменять страницы и вложения destination.
|
|
118
|
+
|
|
119
|
+
### Confluence Cloud
|
|
120
|
+
|
|
121
|
+
- [ ] Создайте [Atlassian API token](https://id.atlassian.com/manage-profile/security/api-tokens).
|
|
122
|
+
- [ ] Используйте `deployment: cloud`, `authType: api-token`, `tokenEnv` и `emailEnv`.
|
|
123
|
+
- [ ] Сохраните API token и email Atlassian-аккаунта в соответствующих env-переменных.
|
|
124
|
+
- [ ] Проверьте доступ аккаунта к source/destination space.
|
|
125
|
+
|
|
126
|
+
## Направления и совместимость
|
|
127
|
+
|
|
128
|
+
| Source | Destination | Поддержка |
|
|
129
|
+
| --- | --- | --- |
|
|
130
|
+
| Yandex Wiki | Confluence | Да |
|
|
131
|
+
| Yandex Wiki | Yandex Wiki | Да, включая другой профиль/инстанс |
|
|
132
|
+
| Confluence | Yandex Wiki | Да |
|
|
133
|
+
| Confluence | Confluence | Да, включая другой профиль/инстанс |
|
|
134
|
+
| Yandex Wiki или Confluence | Markdown | Да |
|
|
135
|
+
| Yandex Wiki или Confluence | статический HTML | Да |
|
|
136
|
+
|
|
137
|
+
| Система | Поддерживаемый контракт | Авторизация |
|
|
138
|
+
| --- | --- | --- |
|
|
139
|
+
| Yandex Wiki | Public API v1; tolerant parsing новых необязательных полей | OAuth или пользовательский IAM; `X-Org-Id`/`X-Cloud-Org-Id` |
|
|
140
|
+
| Confluence Data Center | 7.9+ без искусственной верхней границы; capabilities проверяются до записи | Bearer PAT |
|
|
141
|
+
| Confluence Cloud | Текущий публичный REST v2 для страниц и v1 для attachments | Email + API token |
|
|
142
|
+
|
|
143
|
+
Confluence Server, Data Center Basic Auth и OAuth app-flow пока не поддерживаются. Совместимость определяется preflight-проверкой используемых API/capabilities, а не обещанием для каждой patch-версии.
|
|
144
|
+
|
|
145
|
+
## Параметры `migrate`
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
ywtc migrate --source <locator> --destination <locator|directory> [options]
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
| Параметр | Обязателен | Значения / default | Назначение |
|
|
152
|
+
| --- | --- | --- | --- |
|
|
153
|
+
| `--source <value>` | Да | URL, page ID или slug | Исходная страница |
|
|
154
|
+
| `--destination <value>` | Да | URL, page ID, slug или каталог | Родительская страница либо каталог экспорта |
|
|
155
|
+
| `--source-profile <name>` | Иногда | имя из `connections` | Нужен для неоднозначного короткого ID/slug |
|
|
156
|
+
| `--destination-profile <name>` | Иногда | имя из `connections` | То же для удалённой destination |
|
|
157
|
+
| `--scope <mode>` | Нет | `page`, `subtree` (default), `linked` | Граница выбора страниц |
|
|
158
|
+
| `--format <format>` | Для каталога | `markdown`, `html` | Однозначно включает файловый экспорт |
|
|
159
|
+
| `--archive` | Нет | только с `--format` | Оставляет каталог и создаёт ZIP рядом |
|
|
160
|
+
| `--dry-run` | Нет | `false` | Полный discovery/план без destination writes |
|
|
161
|
+
| `--workdir <path>` | Нет | marker CWD или `~/.ywtc` | Выбирает workspace |
|
|
162
|
+
| `--state <path>` | Нет | `.states/<automatic-id>.json` | Явный state внутри workspace |
|
|
163
|
+
| `--fresh` | Нет | `false` | Не использует mappings; live-run сохраняет backup state |
|
|
164
|
+
| `--concurrency <n>` | Нет | `1..64`, config default `4` | Параллельность оркестрации; профильные лимиты действуют отдельно |
|
|
165
|
+
|
|
166
|
+
Полный URL автоматически сопоставляется с профилем по нормализованному base URL. Для короткого ID/slug профиль выбирается автоматически только при единственном подходящем подключении; иначе CLI перечисляет допустимые имена. Каталог считается файловой destination только вместе с `--format`.
|
|
167
|
+
|
|
168
|
+
### Scope
|
|
169
|
+
|
|
170
|
+
- `page` — только исходная страница.
|
|
171
|
+
- `subtree` — страница и все структурные потомки; режим по умолчанию.
|
|
172
|
+
- `linked` — детерминированный BFS по внутренним ссылкам и page/include references до фиксированной точки. Циклы безопасно завершаются, страница обрабатывается один раз. Внешние и недоступные ссылки не обходятся и отражаются в отчёте.
|
|
173
|
+
|
|
174
|
+
## Частые примеры
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
# Связанные страницы Yandex Wiki → Confluence
|
|
178
|
+
ywtc migrate \
|
|
179
|
+
--source https://wiki.example.ru/team/start \
|
|
180
|
+
--destination https://confluence.example.ru/pages/viewpage.action?pageId=123 \
|
|
181
|
+
--scope linked
|
|
182
|
+
|
|
183
|
+
# Confluence → Yandex Wiki по коротким идентификаторам
|
|
184
|
+
ywtc migrate \
|
|
185
|
+
--source-profile confluence-prod --source 123456 \
|
|
186
|
+
--destination-profile wiki-prod --destination team/archive \
|
|
187
|
+
--scope subtree
|
|
188
|
+
|
|
189
|
+
# Одна страница без потомков
|
|
190
|
+
ywtc migrate --source-profile wiki-prod --source team/start \
|
|
191
|
+
--destination-profile confluence-prod --destination 123 --scope page
|
|
192
|
+
|
|
193
|
+
# Автономный HTML-сайт и ZIP
|
|
194
|
+
ywtc migrate --source-profile confluence-prod --source 123456 \
|
|
195
|
+
--destination ./exports/knowledge-base --format html --scope linked --archive
|
|
196
|
+
|
|
197
|
+
# Markdown-экспорт в отдельном workspace
|
|
198
|
+
ywtc migrate --workdir ./migration --source-profile wiki-prod --source team/start \
|
|
199
|
+
--destination ./export --format markdown --dry-run
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
`doctor` принимает те же `source`, `destination`, profile, `scope` и `format`; с endpoints выполняет только read-only capability-preflight. Без endpoints проверяет workspace, конфигурацию и все секреты.
|
|
203
|
+
|
|
204
|
+
## Файловый экспорт
|
|
205
|
+
|
|
206
|
+
Markdown создаёт `index.md`, `pages/`, `attachments/`, manifest `.ywtc-export.json` и, при деградациях, `_source/`. HTML создаёт автономный адаптивный сайт с теми же данными и локальным `assets/site.css`; он работает через `file://` и на обычном static hosting без CDN/runtime.
|
|
207
|
+
|
|
208
|
+
Экспорт строится в staging-каталоге. Существующий каталог заменяется только при совпадающем ywtc manifest; предыдущая версия сохраняется как timestamped backup. ZIP не перезаписывает уже существующий архив.
|
|
209
|
+
|
|
210
|
+
## State, отчёты и повторный запуск
|
|
211
|
+
|
|
212
|
+
Автоматический state ID строится из канонических профилей и ID source/destination; форма URL/slug/ID и `scope` на него не влияют. Поэтому одна и та же пара endpoints возобновляет один state, а разные пары получают разные файлы.
|
|
213
|
+
|
|
214
|
+
- Повторный запуск обновляет только сопоставленные объекты и не создаёт дубликаты.
|
|
215
|
+
- Страница, изменённая вручную после прошлого запуска, получает `conflict` и не перезаписывается.
|
|
216
|
+
- `--fresh` начинает с чистых mappings; live-run сохраняет прежний state как backup и может создать новые страницы.
|
|
217
|
+
- State schema v1 не мигрируется автоматически и остаётся нетронутой.
|
|
218
|
+
- SIGINT/SIGTERM останавливает постановку новых задач, сохраняет state/report и возвращает `130`/`143`.
|
|
219
|
+
- Каждый запуск создаёт `.states/reports/<run-id>/index.html` и `report.json`: направление, дерево, link graph, циклы, вложения, размеры, деградации, ошибки и side-by-side preview.
|
|
220
|
+
|
|
221
|
+
Коды выхода: `0` — завершено; `1` — partial/ошибка verification; `2` — usage/config/preflight; `130`/`143` — остановка сигналом.
|
|
222
|
+
|
|
223
|
+
## Переход на 2.0
|
|
224
|
+
|
|
225
|
+
Обратной совместимости с предварительным CLI и state v1 нет:
|
|
226
|
+
|
|
227
|
+
| Было | Стало |
|
|
228
|
+
| --- | --- |
|
|
229
|
+
| `--target <value>` | `--destination <value>` |
|
|
230
|
+
| `--single-page` | `--scope page` |
|
|
231
|
+
| Один набор env-подключений | Именованные подключения в `ywtc.config.yaml`; `.env` содержит только секреты |
|
|
232
|
+
| State schema v1 | Новый автоматический provider-neutral state v2 |
|
|
233
|
+
|
|
234
|
+
Старые флаги отклоняются с точной подсказкой. Для переноса создайте новый workspace или сохраните старые state-файлы отдельно и выполните `ywtc init`.
|
|
235
|
+
|
|
236
|
+
## Разработка
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
git clone https://github.com/iwonz/ywtc.git
|
|
240
|
+
cd ywtc
|
|
241
|
+
npm ci
|
|
242
|
+
npm run workspace:init
|
|
243
|
+
npm run check
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
`npm run check` запускает release/hygiene checks, аудит production-зависимостей (high/critical), TypeScript, Biome, Knip, тесты, сборку, проверку устанавливаемого tarball и строгую OpenSpec-валидацию. Изменения оформляются полным OpenSpec-циклом согласно [`AGENTS.md`](AGENTS.md).
|
|
247
|
+
|
|
248
|
+
## Релизы (для сопровождающего)
|
|
249
|
+
|
|
250
|
+
Release Please формирует PR из Conventional Commits. После его проверки и merge workflow повторяет полный quality gate, создаёт GitHub Release, публикует npm-пакет с OIDC provenance и обновляет проверенную Homebrew-формулу. Версии `package.json`, lock-файла и changelog вручную не меняются; регулярные релизы не требуют npm OTP или `NPM_TOKEN`.
|
|
251
|
+
|
|
252
|
+
Если GitHub Release уже создан, а публикация остановилась, повторите существующий тег идемпотентным recovery:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
gh workflow run release.yml --repo iwonz/ywtc -f release_tag=vX.Y.Z
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Recovery проверяет неизменённый tag актуальным trusted validator, не перезаписывает существующую npm-версию и восстанавливает только недостающие artifacts, release notes и Homebrew-формулу.
|
|
259
|
+
|
|
260
|
+
Одноразовая инициализация нового npm-пакета выполняется так:
|
|
261
|
+
|
|
262
|
+
- [ ] Установить npm `>=11.15`, выполнить `npm login` и проверить владельца через `npm whoami`.
|
|
263
|
+
- [ ] Опубликовать placeholder с интерактивной 2FA: `npm run release:bootstrap`; не передавать OTP в файлах, командах или CI.
|
|
264
|
+
- [ ] Выполнить `npm trust github @iwonz/ywtc --file release.yml --repo iwonz/ywtc --allow-publish`.
|
|
265
|
+
- [ ] В **Settings → Actions → General → Workflow permissions** включить **Allow GitHub Actions to create and approve pull requests**; возможности каждого job дополнительно ограничены его `permissions`.
|
|
266
|
+
|
|
267
|
+
Для `@iwonz/ywtc` эта инициализация уже выполнена. Подробности: [npm trusted publishing](https://docs.npmjs.com/trusted-publishers/) и [`npm trust`](https://docs.npmjs.com/cli/v11/commands/npm-trust/).
|
|
268
|
+
|
|
269
|
+
Лицензия: [MIT](LICENSE).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ConfluenceConnectionProfile } from '../config.js';
|
|
2
|
+
import type { AdapterCapabilities, DestinationAdapter, DestinationContainer, DestinationPage, PageReference, SourceAdapter, SourcePage, SourceResource, UploadedResource } from '../domain.js';
|
|
3
|
+
import type { ConfluenceApi } from '../types.js';
|
|
4
|
+
export declare class ConfluenceAdapter implements SourceAdapter, DestinationAdapter {
|
|
5
|
+
readonly profile: ConfluenceConnectionProfile;
|
|
6
|
+
private readonly client;
|
|
7
|
+
readonly kind: "confluence";
|
|
8
|
+
readonly capabilities: AdapterCapabilities;
|
|
9
|
+
constructor(profile: ConfluenceConnectionProfile, client: ConfluenceApi);
|
|
10
|
+
preflight(): Promise<{
|
|
11
|
+
product: string;
|
|
12
|
+
version?: string;
|
|
13
|
+
warnings: string[];
|
|
14
|
+
}>;
|
|
15
|
+
resolvePage(locator: string): Promise<SourcePage>;
|
|
16
|
+
getPage(id: string): Promise<SourcePage>;
|
|
17
|
+
getDescendants(page: SourcePage): Promise<SourcePage[]>;
|
|
18
|
+
resolveReference(from: SourcePage, reference: PageReference): Promise<SourcePage | undefined>;
|
|
19
|
+
listResources(page: SourcePage): Promise<SourceResource[]>;
|
|
20
|
+
downloadResource(resource: SourceResource, destination: string): Promise<import("../types.js").DownloadedFile>;
|
|
21
|
+
resolveContainer(locator: string): Promise<DestinationContainer>;
|
|
22
|
+
findChild(container: DestinationContainer | DestinationPage, title: string): Promise<DestinationPage | undefined>;
|
|
23
|
+
createPage(input: {
|
|
24
|
+
container: DestinationContainer | DestinationPage;
|
|
25
|
+
title: string;
|
|
26
|
+
body: string;
|
|
27
|
+
}): Promise<DestinationPage>;
|
|
28
|
+
updatePage(input: {
|
|
29
|
+
page: DestinationPage;
|
|
30
|
+
title: string;
|
|
31
|
+
body: string;
|
|
32
|
+
expectedFingerprint?: string;
|
|
33
|
+
}): Promise<DestinationPage>;
|
|
34
|
+
uploadResource(input: {
|
|
35
|
+
page: DestinationPage;
|
|
36
|
+
name: string;
|
|
37
|
+
filePath: string;
|
|
38
|
+
size?: number;
|
|
39
|
+
mimeType?: string;
|
|
40
|
+
existingId?: string;
|
|
41
|
+
}): Promise<UploadedResource>;
|
|
42
|
+
listUploadedResources(page: DestinationPage): Promise<UploadedResource[]>;
|
|
43
|
+
verifyPage(page: DestinationPage): Promise<DestinationPage>;
|
|
44
|
+
renderPageReference(page: DestinationPage, label: string, anchor?: string): string;
|
|
45
|
+
renderResourceReference(resource: UploadedResource, label: string, image: boolean): string;
|
|
46
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { createReadStream } from 'node:fs';
|
|
3
|
+
import { extractPageReferences } from '../content-model.js';
|
|
4
|
+
const capabilities = {
|
|
5
|
+
readPages: true,
|
|
6
|
+
readHierarchy: true,
|
|
7
|
+
readResources: true,
|
|
8
|
+
writePages: true,
|
|
9
|
+
writeResources: true,
|
|
10
|
+
verifyWrites: true,
|
|
11
|
+
};
|
|
12
|
+
function canonical(profile, id) {
|
|
13
|
+
return `${profile.name}:confluence:${id}`;
|
|
14
|
+
}
|
|
15
|
+
function fingerprint(page) {
|
|
16
|
+
return createHash('sha256').update(`${page.title}\0${page.body?.storage?.value ?? ''}\0${page.version?.number ?? ''}`).digest('hex');
|
|
17
|
+
}
|
|
18
|
+
function sourcePage(profile, client, page) {
|
|
19
|
+
const rawContent = page.body?.storage?.value ?? '';
|
|
20
|
+
return {
|
|
21
|
+
provider: 'confluence',
|
|
22
|
+
profile: profile.name,
|
|
23
|
+
id: page.id,
|
|
24
|
+
canonicalId: canonical(profile, page.id),
|
|
25
|
+
title: page.title,
|
|
26
|
+
locator: page.id,
|
|
27
|
+
url: client.pageWebUrl(page),
|
|
28
|
+
...(page.ancestors?.at(-1)?.id ? { parentId: page.ancestors.at(-1).id } : {}),
|
|
29
|
+
space: page.space.key,
|
|
30
|
+
rawContent,
|
|
31
|
+
rawFormat: 'confluence-storage',
|
|
32
|
+
...(page.version?.number ? { version: String(page.version.number) } : {}),
|
|
33
|
+
references: extractPageReferences(rawContent, 'confluence-storage'),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function destinationPage(profile, client, page) {
|
|
37
|
+
return {
|
|
38
|
+
provider: 'confluence',
|
|
39
|
+
profile: profile.name,
|
|
40
|
+
id: page.id,
|
|
41
|
+
canonicalId: canonical(profile, page.id),
|
|
42
|
+
title: page.title,
|
|
43
|
+
url: client.pageWebUrl(page),
|
|
44
|
+
locator: page.id,
|
|
45
|
+
space: page.space.key,
|
|
46
|
+
...(page.version?.number ? { version: String(page.version.number) } : {}),
|
|
47
|
+
fingerprint: fingerprint(page),
|
|
48
|
+
contentLength: Buffer.byteLength(page.body?.storage?.value ?? ''),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export class ConfluenceAdapter {
|
|
52
|
+
profile;
|
|
53
|
+
client;
|
|
54
|
+
kind = 'confluence';
|
|
55
|
+
capabilities = capabilities;
|
|
56
|
+
constructor(profile, client) {
|
|
57
|
+
this.profile = profile;
|
|
58
|
+
this.client = client;
|
|
59
|
+
}
|
|
60
|
+
async preflight() {
|
|
61
|
+
const info = await this.client.preflight?.();
|
|
62
|
+
return { product: info?.product ?? 'Confluence', ...(info?.version ? { version: info.version } : {}), warnings: [] };
|
|
63
|
+
}
|
|
64
|
+
async resolvePage(locator) {
|
|
65
|
+
return sourcePage(this.profile, this.client, await this.client.resolveTarget(locator));
|
|
66
|
+
}
|
|
67
|
+
async getPage(id) {
|
|
68
|
+
return sourcePage(this.profile, this.client, await this.client.getPage(id));
|
|
69
|
+
}
|
|
70
|
+
async getDescendants(page) {
|
|
71
|
+
return (await this.client.getDescendants(page.id)).map((item) => sourcePage(this.profile, this.client, item));
|
|
72
|
+
}
|
|
73
|
+
async resolveReference(from, reference) {
|
|
74
|
+
if (reference.kind !== 'page')
|
|
75
|
+
return undefined;
|
|
76
|
+
const href = reference.href ?? '';
|
|
77
|
+
if (href.startsWith('confluence-page:'))
|
|
78
|
+
return this.getPage(href.slice('confluence-page:'.length));
|
|
79
|
+
if (href.startsWith('page:')) {
|
|
80
|
+
const value = href.slice('page:'.length);
|
|
81
|
+
if (/^\d+$/.test(value))
|
|
82
|
+
return this.getPage(value);
|
|
83
|
+
const found = await this.client.findPageByTitle(from.space ?? '', value);
|
|
84
|
+
return found ? sourcePage(this.profile, this.client, await this.client.getPage(found.id)) : undefined;
|
|
85
|
+
}
|
|
86
|
+
if (reference.pageTitle) {
|
|
87
|
+
const referencedSpace = reference.href?.includes(':') ? reference.href.split(':', 1)[0] : undefined;
|
|
88
|
+
const found = await this.client.findPageByTitle(referencedSpace || from.space || '', reference.pageTitle);
|
|
89
|
+
return found ? sourcePage(this.profile, this.client, await this.client.getPage(found.id)) : undefined;
|
|
90
|
+
}
|
|
91
|
+
if (/^(?:https?:\/\/|\/)|viewpage\.action|\/(?:pages|spaces)\//i.test(href)) {
|
|
92
|
+
const url = new URL(href, `${this.profile.baseUrl}/`);
|
|
93
|
+
if (url.origin !== new URL(this.profile.baseUrl).origin)
|
|
94
|
+
return undefined;
|
|
95
|
+
return sourcePage(this.profile, this.client, await this.client.resolveTarget(url.toString()));
|
|
96
|
+
}
|
|
97
|
+
const [space, title] = href.includes(':') ? href.split(':', 2) : [from.space ?? '', href];
|
|
98
|
+
if (!title)
|
|
99
|
+
return undefined;
|
|
100
|
+
const found = await this.client.findPageByTitle(space ?? '', title);
|
|
101
|
+
return found ? sourcePage(this.profile, this.client, await this.client.getPage(found.id)) : undefined;
|
|
102
|
+
}
|
|
103
|
+
async listResources(page) {
|
|
104
|
+
return (await this.client.listAttachments(page.id)).map((attachment) => ({
|
|
105
|
+
provider: 'confluence',
|
|
106
|
+
id: attachment.id,
|
|
107
|
+
pageId: page.id,
|
|
108
|
+
name: attachment.title,
|
|
109
|
+
...(attachment.extensions?.fileSize !== undefined ? { size: attachment.extensions.fileSize } : {}),
|
|
110
|
+
...(attachment.metadata?.mediaType ? { mimeType: attachment.metadata.mediaType } : {}),
|
|
111
|
+
...(attachment._links?.download ? { downloadUrl: attachment._links.download } : {}),
|
|
112
|
+
kind: attachment.metadata?.mediaType?.startsWith('image/') ? 'image' : 'attachment',
|
|
113
|
+
metadata: { attachment },
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
downloadResource(resource, destination) {
|
|
117
|
+
return this.client.downloadAttachment(resource.pageId, resource.metadata?.attachment, destination);
|
|
118
|
+
}
|
|
119
|
+
async resolveContainer(locator) {
|
|
120
|
+
const page = await this.client.resolveTarget(locator);
|
|
121
|
+
return {
|
|
122
|
+
provider: 'confluence', profile: this.profile.name, id: page.id, canonicalId: canonical(this.profile, page.id),
|
|
123
|
+
title: page.title, url: this.client.pageWebUrl(page), space: page.space.key, locator: page.id,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
async findChild(container, title) {
|
|
127
|
+
const space = container.space;
|
|
128
|
+
if (!space)
|
|
129
|
+
return undefined;
|
|
130
|
+
const found = await this.client.findPageByTitle(space, title);
|
|
131
|
+
if (!found)
|
|
132
|
+
return undefined;
|
|
133
|
+
return destinationPage(this.profile, this.client, await this.client.getPage(found.id));
|
|
134
|
+
}
|
|
135
|
+
async createPage(input) {
|
|
136
|
+
const space = input.container.space;
|
|
137
|
+
if (!space)
|
|
138
|
+
throw new Error(`Confluence destination ${input.container.id} is missing a space key`);
|
|
139
|
+
return destinationPage(this.profile, this.client, await this.client.createPage({
|
|
140
|
+
spaceKey: space, parentId: input.container.id, title: input.title, storage: input.body,
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
async updatePage(input) {
|
|
144
|
+
if (input.expectedFingerprint) {
|
|
145
|
+
const current = destinationPage(this.profile, this.client, await this.client.getPage(input.page.id));
|
|
146
|
+
if (current.fingerprint !== input.expectedFingerprint)
|
|
147
|
+
throw new Error(`Destination conflict for Confluence page ${input.page.id}: content changed since the last verified run`);
|
|
148
|
+
}
|
|
149
|
+
return destinationPage(this.profile, this.client, await this.client.updatePage({ pageId: input.page.id, title: input.title, storage: input.body }));
|
|
150
|
+
}
|
|
151
|
+
async uploadResource(input) {
|
|
152
|
+
const uploaded = await this.client.uploadAttachment({
|
|
153
|
+
pageId: input.page.id,
|
|
154
|
+
filename: input.name,
|
|
155
|
+
file: createReadStream(input.filePath),
|
|
156
|
+
...(input.size !== undefined ? { contentLength: input.size } : {}),
|
|
157
|
+
...(input.mimeType ? { mimeType: input.mimeType } : {}),
|
|
158
|
+
...(input.existingId ? { existingAttachmentId: input.existingId } : {}),
|
|
159
|
+
});
|
|
160
|
+
return {
|
|
161
|
+
id: uploaded.id,
|
|
162
|
+
name: uploaded.title,
|
|
163
|
+
...(uploaded.extensions?.fileSize !== undefined ? { size: uploaded.extensions.fileSize } : {}),
|
|
164
|
+
...(uploaded._links?.download ? { url: uploaded._links.download } : {}),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
async listUploadedResources(page) {
|
|
168
|
+
return (await this.client.listAttachments(page.id)).map((attachment) => ({
|
|
169
|
+
id: attachment.id,
|
|
170
|
+
name: attachment.title,
|
|
171
|
+
...(attachment.extensions?.fileSize !== undefined ? { size: attachment.extensions.fileSize } : {}),
|
|
172
|
+
...(attachment._links?.download ? { url: attachment._links.download } : {}),
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
175
|
+
async verifyPage(page) {
|
|
176
|
+
return destinationPage(this.profile, this.client, await this.client.getPage(page.id));
|
|
177
|
+
}
|
|
178
|
+
renderPageReference(page, label, anchor) {
|
|
179
|
+
return `<ac:link${anchor ? ` ac:anchor="${anchor}"` : ''}><ri:page ri:content-title="${page.title}"/><ac:link-body>${label}</ac:link-body></ac:link>`;
|
|
180
|
+
}
|
|
181
|
+
renderResourceReference(resource, label, image) {
|
|
182
|
+
return image
|
|
183
|
+
? `<ac:image ac:alt="${label}"><ri:attachment ri:filename="${resource.name}"/></ac:image>`
|
|
184
|
+
: `<ac:link><ri:attachment ri:filename="${resource.name}"/><ac:plain-text-link-body><![CDATA[${label}]]></ac:plain-text-link-body></ac:link>`;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=confluence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confluence.js","sourceRoot":"","sources":["../../src/adapters/confluence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createConfluenceClient } from '../clients/confluence-factory.js';
|
|
2
|
+
import { YandexWikiClient } from '../clients/yandex-wiki.js';
|
|
3
|
+
import { ConfluenceAdapter } from './confluence.js';
|
|
4
|
+
import { YandexAdapter } from './yandex.js';
|
|
5
|
+
export function createProviderAdapter(profile, config) {
|
|
6
|
+
if (profile.type === 'yandex-wiki') {
|
|
7
|
+
return new YandexAdapter(profile, new YandexWikiClient(profile, config.timeoutMs, profile.limits));
|
|
8
|
+
}
|
|
9
|
+
return new ConfluenceAdapter(profile, createConfluenceClient(profile, config.timeoutMs));
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/adapters/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,sBAAsB,EAAC,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAC,gBAAgB,EAAC,MAAM,2BAA2B,CAAC;AAG3D,OAAO,EAAC,iBAAiB,EAAC,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAC;AAE1C,MAAM,UAAU,qBAAqB,CAAC,OAA0B,EAAE,MAAiB;IACjF,IAAI,OAAO,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;QACnC,OAAO,IAAI,aAAa,CAAC,OAAO,EAAE,IAAI,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACrG,CAAC;IACD,OAAO,IAAI,iBAAiB,CAAC,OAAO,EAAE,sBAAsB,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;AAC3F,CAAC"}
|